package com.cfpamf.ms.insur.pay.service;

import com.cfpamf.ms.insur.pay.dao.BuildTrxMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * 流水号构造服务 构造
 * <p>
 * 8位时间戳+3位系统编码+3位业务类型+2位分库+2位分表位+4位保留位+8位seq
 */
@Service
@Slf4j
public class BuildTrxService {

    /**
     * 系统编码
     */
    private static final String SYS_CODE = "056";

    /**
     * 支付业务类型 3位系统编码+3位业务类型+2位分库+2位分表位+4位保留位
     **/
    private static final String TRX_NO_PREFIX = SYS_CODE + "11100000000";

    /**
     * 退款业务类型 3位系统编码+3位业务类型+2位分库+2位分表位+4位保留位
     */
    private static final String REFUND_TRX_NO_PREFIX = SYS_CODE + "22200000000";

    /**
     * 对账批次业务类型 3位系统编码+3位业务类型+2位分库+2位分表位+4位保留位
     **/
    private static final String RECONCILIATION_BATCH_NO = SYS_CODE + "33300000000";

    /**
     * DATE_FORMAT
     */
    private static final DateTimeFormatter DEFAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");

    /**
     * 8位时间戳+3位系统编码+3位业务类型+2位分库+2位分表位+4位保留位+8位seq
     */
    private final BuildTrxMapper buildMapper;

    @Autowired
    public BuildTrxService(BuildTrxMapper buildMapper) {
        this.buildMapper = buildMapper;
    }

    /**
     * 获取支付流水号
     **/
    public String buildPayTrxNo() {
        String trxNoSeq = this.getSeqNextValue("PAY_TRX_NO_SEQ");
        String dateString = LocalDate.now().format(DEFAULT_DATE_FORMAT);
        return dateString + TRX_NO_PREFIX + trxNoSeq.substring(trxNoSeq.length() - 8);
    }

    /**
     * 获取退款流水号
     **/
    public String buildRefundTrxNo() {
        String trxNoSeq = this.getSeqNextValue("REFUND_TRX_NO_SEQ");
        String substring = trxNoSeq.substring(trxNoSeq.length() - 8);
        String dateString = LocalDate.now().format(DEFAULT_DATE_FORMAT);
        return dateString + REFUND_TRX_NO_PREFIX + substring;
    }

    /**
     * 获取对账批次号
     **/
    public String buildReconciliationNo() {
        String batchNoSeq = this.getSeqNextValue("RECONCILIATION_BATCH_NO_SEQ");
        String dateString = LocalDate.now().format(DEFAULT_DATE_FORMAT);
        return dateString + RECONCILIATION_BATCH_NO + batchNoSeq.substring(batchNoSeq.length() - 8);
    }

    /**
     * 不应该与其他地方公用事物
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
    public String getSeqNextValue(String seqName) {
        try {
            return buildMapper.getSeqNextValue(seqName);
        } catch (Exception e) {
            log.error("生成序号异常：" + "seqName=" + seqName, e);
            throw new RuntimeException("获取序列号失败：" + seqName);
        }
    }
}
